//
//  ControlFlowGraph.cpp
//  ConstructGccfg2.0
//
//  Created by Bryce Holton on 12/4/12.
//  Copyright (c) 2012 Bryce Holton. All rights reserved.
//

#include "ControlFlowGraph.h"
#include "LoopBlock.h"

ControlFlowGraph::ControlFlowGraph()
{
    rootBlock = NULL;
    exitBlock = NULL;
}
ControlFlowGraph::~ControlFlowGraph()
{
    for (set<BasicBlock *>::iterator it = blockSet.begin(); it != blockSet.end(); ++it)
    {
        delete *it;
        **it = NULL;
    }
    blockSet.clear();
}
BasicBlock *ControlFlowGraph::FindBlockInSet(int blockId)
{
    //We have to iterate over the whole list as we need to compare the ids.
    BasicBlock *returnBlock = NULL;
    
    for (set<BasicBlock *>::iterator itr = blockSet.begin();
         itr != blockSet.end() && returnBlock == NULL;
         itr++)
    {
        if ((*itr)->GetId() == blockId)
        {
            returnBlock = *itr;
        }
    }
    
    return returnBlock;
}
void ControlFlowGraph::RemoveBlockFromSet(BasicBlock &toRemove)
{
    blockSet.erase ( blockSet.find (&toRemove) );
}
void ControlFlowGraph::RemoveBlocksNotInThisSet(set<BasicBlock *> &blocksToRemove)
{
    set<BasicBlock *> blockListIntersection;
    
    set_intersection(blockSet.begin(), blockSet.end(),
                   blocksToRemove.begin(), blocksToRemove.end(),
                   inserter(blockListIntersection, blockListIntersection.begin()));
    for (set<BasicBlock *>::iterator itr = blockListIntersection.begin(); itr != blockListIntersection.end(); itr++)
    {
        this->RemoveBlockFromSet(**itr);
    }
}
void ControlFlowGraph::FindLoopsInBlockSet(ControlFlowGraphLoop &loop)
{
    BasicBlock *loopHead = loop.GetRootBlock();
    
    for (set<BasicBlock *>::iterator it = blockSet.begin(); it != blockSet.end(); ++it)
    {
        vector<Edge<BasicBlock *> *> childEdges = (*it)->GetDecendantEdges();
        for (unsigned int j = 0; j < childEdges.size(); j++)
        {
            BasicBlock *child =  childEdges[j]->GetDecendant();
            
            if (child == loopHead)
            {
                LoopBlock *loopPlaceHolder = new LoopBlock( loop.GetLoopId() );
                
                (*it)->ReplaceChild(*loopHead, *loopPlaceHolder);
                blockSet.insert(loopPlaceHolder);
                loopPlaceHolder->SetDecendantEdge(*loop.FindLoopExitBlock(blockSet));
            }
        }
    }
}
void ControlFlowGraph::CleanUpBlocks()
{
    set<BasicBlock *> setOfChildren = GetSetOfChildrenThisGraph();
    
    
}
void ControlFlowGraph::DepthFirstSearch(BasicBlock &)
{
    
}
void ControlFlowGraph::SetFunctionName(string fName)
{
    functionName = fName;
}
void ControlFlowGraph::SetRootBlock(BasicBlock &rBlock)
{
    rootBlock = &rBlock;
}
void ControlFlowGraph::SetExitBlock(BasicBlock &eBlock)
{
    exitBlock = &eBlock;
}
void ControlFlowGraph::SetBlockSet(set<BasicBlock *> &bSet)
{
    blockSet = bSet;
}
string ControlFlowGraph::GetFunctionName()
{
    return functionName;
}
BasicBlock *ControlFlowGraph::GetRootBlock()
{
    return rootBlock;
}
BasicBlock *ControlFlowGraph::GetExitBlock()
{
    return exitBlock;
}
set<BasicBlock *> ControlFlowGraph::GetBlockSet()
{
    return blockSet;
}
set<BasicBlock *> ControlFlowGraph::GetSetOfChildrenThisGraph()
{
    set<BasicBlock *> setOfChildren;
    
    for (set<BasicBlock *>::iterator it = blockSet.begin(); it != blockSet.end(); ++it)
    {
        vector<Edge<BasicBlock *> *> children = (*it)->GetDecendantEdges();
        
        for (unsigned int j = 0; j < children.size(); j++)
        {
            setOfChildren.insert(children[j]->GetDecendant());
        }
    }
    
    return setOfChildren;
}
